package ex03.connector.http;


import ex03.ServletProcessor;
import ex03.StaticResourceProcessor;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.StringManager;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

/**
 * @packgeName: ex03.connector.http
 * @ClassName: HttpProcessor
 * @copyright: CopyLeft
 * @description:<描述>
 * @author: lili
 * @date: 2017/8/11-16:20
 * @version: 1.0
 * @since: JDK 1.8
 */
public class HttpProcessor {

    private HttpConnector connector = null;
    private HttpRequest request;
    private HttpRequestLine requestLine = new HttpRequestLine();
    private HttpResponse response;
    protected String method = null;
    protected String queryString = null;

    protected StringManager sm = StringManager.getManager("ex03.connector.http");

    public HttpProcessor(HttpConnector httpConnector) {
    }

    public void process(Socket socket) {
        SocketInputStream input = null;
        OutputStream output = null;

        try {
            input = new SocketInputStream(socket.getInputStream(),2048);
            output = socket.getOutputStream();
            request = new HttpRequest(input);
            response = new HttpResponse(output);
            response.setRequest(request);
            response.setHeader("Server","Pymont Servlet Container");
            parseRequest(input,output);
            parseHeader(input);
            if (request.getRequestURI().startsWith("/servlet/")) {
                ServletProcessor processor = new ServletProcessor();
                processor.process(request, response);
            }
            else {
                StaticResourceProcessor processor = new StaticResourceProcessor();
                processor.process(request, response);
            }

            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void parseRequest(SocketInputStream input, OutputStream output) throws IOException, ServletException {

        input.readRequestLine(requestLine);
        String method = new String(requestLine.method,0,requestLine.methodEnd);
        String uri = null;
        String protocol = new String(requestLine.protocol,0,requestLine.protocolEnd);

        if(method.length() < 1) {
            throw new ServletException("Missing HTTP request method");
        }else if(requestLine.uriEnd < 1){
            throw new ServletException("Missing HTTP request URI");
        }

        int question = requestLine.indexOf("?");
        if(question>=0){

            request.setQueryString(new String(requestLine.uri,question+1,requestLine.uriEnd-question-1));
            uri = new String(requestLine.uri, 0, requestLine.uriEnd);
        }else{
            request.setQueryString(null);
            uri = new String(requestLine.uri, 0, requestLine.uriEnd);
        }

        if(!uri.startsWith("/")){
            int pos = uri.indexOf("://");
            if(pos!=-1){
                pos = uri.indexOf("/",pos+3);
                if(pos!=-1){
                    uri = "";
                }else{
                    uri = uri.substring(pos);
                }
            }
        }

        String match = ";jsessionid=";
        int semicolon = uri.indexOf(match);
        if(semicolon>0){
            String rest = uri.substring(semicolon+match.length());
            int semicolon2 = rest.indexOf(";");
            if(semicolon2>0){
                request.setRequestedSessionId(rest.substring(0,semicolon2));
                rest = rest.substring(semicolon2);
            }else{
                request.setRequestedSessionId(rest);
                rest = "";
            }
            request.setRequestedSessionURL(true);
            uri = uri.substring(0,semicolon) + rest;
        }else{
            request.setRequestedSessionId(null);
            request.setRequestedSessionURL(false);
        }

        String normalizedUri = normalize(uri);

        ((HttpRequest)request).setMethod(method);
        request.setProtocol(protocol);
        if(normalizedUri!=null){
            ((HttpRequest) request).setRequestURI(normalizedUri);

        }else{
            ((HttpRequest) request).setRequestURI(uri);
        }

        if(normalizedUri==null){
            throw new ServletException("Invalid URI: " + uri + "'");
        }

    }

    private void parseHeader(SocketInputStream input) throws IOException, ServletException {

        while(true){

            HttpHeader header = new HttpHeader();
            input.readHeader(header);
            if(header.nameEnd == 0){
                if(header.valueEnd == 0){
                    return;
                }else{
                    throw new ServletException(sm.getString("httpProcessor.parseHeaders.colon"));
                }
            }
            String name = new String(header.name,0,header.nameEnd);
            String value = new String(header.value,0,header.valueEnd);
            request.addHeader(name,value);
            if(name.equals("cookie")){
                Cookie cookies[] = RequestUtil.parseCookieHeader(value);
                for (int i = 0; i < cookies.length; i++) {
                    if(cookies[i].getName().equals("jsessionid")){
                        if(!request.isRequestedSessionIdFromCookie()){
                            request.setRequestedSessionId(cookies[i].getValue());
                            request.setRequestedSessionCookie(true);
                            request.setRequestedSessionURL(false);
                        }
                    }
                    request.addCookie(cookies[i]);
                }
            }else if(name.equals("content-length")){

                int n = -1;
                try{
                    n = Integer.parseInt(value);
                }catch (Exception e){
                    throw new ServletException(sm.getString("httpProcessor.parseHeaders.contentLength"));
                }
                request.setContentLength(n);

            }else if(name.equals("content-type")){
                request.setContentType(value);
            }
        }
    }

    protected String normalize(String path){
        return "";
    }


}
